package top.jfunc.common.compress;

import top.jfunc.common.utils.ArrayUtil;
import top.jfunc.common.utils.IoUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * zip压缩算法实现压缩解压
 * @author xiongshiyan at 2022/5/26 , contact me with email yanshixiong@126.com or phone 15208384257
 */
public class ZipCompressor implements Compressor{
    private int bufferSize = 1024;
    public ZipCompressor(){
    }
    public ZipCompressor(int bufferSize){
        this.bufferSize = bufferSize;
    }


    @Override
    public byte[] compress(byte[] src, int offset, int length) throws CompressException {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             ZipOutputStream zout = new ZipOutputStream(out)){

            //设置ZipEntry对象，并对需要压缩的文件命名
            zout.putNextEntry(new ZipEntry("0"));

            zout.write(src, offset, length);
            //关闭当前ZIP条目并定位流以读取下一个条目，关闭ZipEntry，与putNextEntry对应
            zout.closeEntry();

            return out.toByteArray();

        } catch (Exception e) {
            throw new CompressException(e);
        }
    }

    @Override
    public byte[] compress(byte[] src, byte[]... more) throws CompressException {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             ZipOutputStream zout = new ZipOutputStream(out)){

            //设置ZipEntry对象，并对需要压缩的文件命名
            zout.putNextEntry(new ZipEntry("0"));

            zout.write(src);

            if(ArrayUtil.isNotEmpty(more)){
                for (byte[] bytes : more) {
                    zout.write(bytes);
                }
            }

            //关闭当前ZIP条目并定位流以读取下一个条目，关闭ZipEntry，与putNextEntry对应
            zout.closeEntry();

            return out.toByteArray();

        } catch (Exception e) {
            throw new CompressException(e);
        }
    }

    @Override
    public byte[] compress(InputStream src) throws CompressException {

        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             ZipOutputStream zout = new ZipOutputStream(out)){

            //设置ZipEntry对象，并对需要压缩的文件命名
            zout.putNextEntry(new ZipEntry("0"));

            IoUtil.copy(src,zout,bufferSize);

            //关闭当前ZIP条目并定位流以读取下一个条目，关闭ZipEntry，与putNextEntry对应
            zout.closeEntry();

            return out.toByteArray();

        } catch (Exception e) {
            throw new CompressException(e);
        }
    }

    @Override
    public byte[] unCompress(byte[] src, int offset, int length) throws CompressException {
        try (ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(src, offset, length));
             ByteArrayOutputStream out = new ByteArrayOutputStream()){

            zin.getNextEntry();

            IoUtil.copy(zin,out,bufferSize);

            return out.toByteArray();

        } catch (Exception e) {
            throw new CompressException(e);
        }
    }
    @Override
    public byte[] unCompress(InputStream src) throws CompressException {
        try (ZipInputStream zin = new ZipInputStream(src);
             ByteArrayOutputStream out = new ByteArrayOutputStream()){

            zin.getNextEntry();

            IoUtil.copy(zin,out,bufferSize);

            return out.toByteArray();

        } catch (Exception e) {
            throw new CompressException(e);
        }
    }

    @Override
    public String toString(){
        return getClass().getName();
    }
}
